package arduino;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Enumeration;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;

import net.udp.server.UDPServer;


public class AServer  
implements SerialPortEventListener
{
	SerialPort serialPort;
        /** The port we're normally going to use. */
	private static final String PORT_NAMES[] = { 
			"/dev/tty.usbserial-A9007UX1", // Mac OS X
			"/dev/ttyUSB0", // Linux
			"COM3", // Windows
	};
	/**
	* A BufferedReader which will be fed by a InputStreamReader 
	* converting the bytes into characters 
	* making the displayed results codepage independent
	*/
	private BufferedReader input;
	/** The output stream to the port */
	private BufferedOutputStream output;

	private final int DEFAULT_VEL = 0;
	private final int DEFAULT_DIRECTION = 0;
	private final int DEFAULT_ANGLE = 90;
	
	private boolean is_ready = false;
	private int vel = DEFAULT_VEL  ;	
	private int beep = 0 ;	
	private int direction = DEFAULT_DIRECTION;	
	private int angle = DEFAULT_ANGLE;
	
	private JSlider slider_angle,slider_vel,slider_direction;
	private JButton button ;
	public String outputLine;
	/** Milliseconds to block while waiting for port open */
	private static final int TIME_OUT = 2000;
	/** Default bits per second for COM port. */
	private static final int DATA_RATE = 9600;

	
	private static AServer instance = null;
	
	
	
	public static void main(String[] args) throws Exception {

		AServer ai =  AServer.getInstance();
		while(!ai.is_ready)
		{
			try {Thread.sleep(500);} catch (InterruptedException ie) {}
		}
		
		
		
		AProtocol a = new AProtocol();
		a.in_angle=120;
		a.in_vel=128;
		a.in_direction=1;
		a.in_beep_hz=255;
		a.in_beep_msec=1000;
		
		ai.sendMessage(a);
		
		try {Thread.sleep(1500);} catch (InterruptedException ie) {}
		a.in_angle=60;
		a.in_vel=0;
		a.in_direction=0;
		a.in_beep_msec=0;
		ai.sendMessage(a);
		
		try {Thread.sleep(1500);} catch (InterruptedException ie) {}
		a.in_angle=60;
		a.in_vel=128;
		a.in_direction=0;
		ai.sendMessage(a);
		
		try {Thread.sleep(1500);} catch (InterruptedException ie) {}
		a.in_angle=90;
		a.in_vel=0;
		a.in_direction=0;
		ai.sendMessage(a);
		

		
	}
	
	
	public static AServer getInstance()  
	{
		if(instance==null)
			instance=new AServer();
		return instance;
	}
	
	
	private AServer() {
//		UDPServer.getInstance().run();
		
		
		
		
		CommPortIdentifier portId = null;
		Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();

		//First, Find an instance of serial port as set in PORT_NAMES.
		while (portEnum.hasMoreElements()) {
			CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
			for (String portName : PORT_NAMES) {
				if (currPortId.getName().equals(portName)) {
					portId = currPortId;
					break;
				}
			}
		}
		if (portId == null) {
			System.out.println("Could not find COM port.");
			return;
		}

		try {
			// open serial port, and use class name for the appName.
			serialPort = (SerialPort) portId.open(this.getClass().getName(),
					TIME_OUT);
			
			 

			// set port parameters
			serialPort.setSerialPortParams(DATA_RATE,
					SerialPort.DATABITS_8,
					SerialPort.STOPBITS_1,
					SerialPort.PARITY_NONE);

			
			
			// open the streams
			input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
			output =   new BufferedOutputStream(serialPort.getOutputStream());
			

			// add event listeners
			serialPort.addEventListener(this);
			serialPort.notifyOnDataAvailable(true);
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println(e.toString());
		}
		
		gui();
		
		
		
		  
		  
	}

	/**
	 * This should be called when you stop using the port.
	 * This will prevent port locking on platforms like Linux.
	 */
	public synchronized void close() {
		if (serialPort != null) {
			serialPort.removeEventListener();
			serialPort.close();
		}
	}

	/**
	 * Handle an event on the serial port. Read the data and print it.
//	 */
	public synchronized void serialEvent(SerialPortEvent oEvent) {
		if (  oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
			try {
				
				outputLine = null;
				 while((outputLine= input.readLine())!=null )
				 {
					 System.out.println(" Arduino > Java : "+outputLine);
					 is_ready=true;
				 }				
//				System.out.println("=============================\n");
			
//				input.reset();
				
			} catch (Exception e) {
				System.err.println(e.toString());
			}
		}
		
		
		
	}
	
	
	
	public void sendMessage(AProtocol a) throws IOException
	{		
//		output = serialPort.getOutputStream();
	
		

//
		    int[]array = a.toArray();
			for(int i=0;i<5;i++)
			{
				if(array[i]>255)
					{
						System.out.println("Warning : "+array[i]+">255");
						array[i]=255;
					}
				output.write(array[i]);
			}
			output.flush();

			

			
			System.out.println("DEBUG : Send Message [ OK ] "+a);
//			output.close();
//			output = serialPort.getOutputStream();
		
			
			
			
			
			
		
	}
	
	
	
	
//	@Override
//	protected void finalize() throws Throwable {
//		System.out.println("Finalize...");
//		vel = DEFAULT_VEL;
//		sendMessage();
//		super.finalize();
//	}

	
	public void gui()
	{
		System.out.println("Gui launched!");
		JFrame f = new JFrame();
		

		f.add(new JLabel("AServer started"));
		f.pack();
		f.setVisible(true);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}


	
	public AProtocol process(AProtocol a) throws IOException {
		sendMessage(a);
		return AProtocol.parse(outputLine);
		
	}


	public boolean isReady() {
		
		return is_ready;
	}
	
	

	
//	private static UDPServer instance = null;
	
//  public static UDPServer getInstance()
//  {
//	  if(instance==null)
//		try {
//			instance=new UDPServer();
//		} catch (Exception e) {			
//			log.error(e.getLocalizedMessage());
//		    e.printStackTrace();
//		} 
//	  return instance;
//  }
  
  
  
//  private UDPServer() throws InstantiationException, IllegalAccessException, ClassNotFoundException
//  {
//	 
//	  props = UDPProps.getInstance();	
//	
//	  port=props.getInt("server.port");
//	  BUFFERSIZE=props.getInt("datagram.buffersize");	 
//	   
//	  handler = (RequestHandler)(Class.forName(props.getString("server.requesthandler")).newInstance());
//	  
//	  
//  }

	
	
	
}